package com.store.orm.mysql.reflection;

import com.store.orm.mysql.MySQLUtil;
import com.store.orm.mysql.crud.Delete;
import com.store.orm.mysql.crud.filter.Filtration;
import com.store.orm.mysql.crud.impl.MySQLDelete;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.LinkedHashMap;
import java.util.List;

/**
 * @author 宫静雨
 * @version 1.0
 */
public class DeleteProxy implements InvocationHandler {
    private MySQLUtil UTIL;
    private static final Logger logger = LoggerFactory.getLogger(DeleteProxy.class);

    private MySQLDelete mySQLDelete;

    public DeleteProxy(MySQLDelete mySQLDelete) {
        this.mySQLDelete = mySQLDelete;
        this.UTIL = mySQLDelete.getUTIL();
    }

    public Delete proxy() {
        return (Delete) Proxy.newProxyInstance(mySQLDelete.getClass().getClassLoader(),
                new Class[]{Delete.class}, this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object invoke = method.invoke(mySQLDelete, args);
        Connection connection = UTIL.getConnection();

        if (method.getName().equals("delete")) {
            if (args.length > 1 && args[1] instanceof Filtration) {
                String sql = (String) invoke;
                if (UTIL.isLogged()) {
                    logger.info(">>> {}", sql);
                }
                if (!sql.contains("WHERE") && UTIL.isTruncate()) {
                    connection.createStatement().execute(sql);
                    logger.warn("执行了全表删除: {}", sql);
                } else if (sql.contains("WHERE")) {
                    connection.createStatement().execute(sql);
                }
            } else {
                LinkedHashMap<String, List<Object>> map =
                        (LinkedHashMap<String, List<Object>>) invoke;
                map.forEach((k, v) -> {
                    try {
                        PreparedStatement ps = connection.prepareStatement(k);
                        for (int i = 0; i < v.size(); i++) {
                            ps.setObject(i + 1, v.get(i));
                        }
                        int update = ps.executeUpdate();
                        if (UTIL.isLogged()) {
                            logger.info(">>> {}", k);
                            logger.info("<<< {}", v);
                            if (update == 1) {
                                logger.info("删除数据: {}", true);
                            } else {
                                logger.info("删除数据: {}", false);
                            }
                        }
                    } catch (SQLException e) {
                        logger.error("执行SQL出错: {}", e.getMessage());
                    }
                });
            }
        } else if (method.getName().equals("deleteMany")) {
            List<String> sqls = (List<String>) invoke;
            Statement statement = connection.createStatement();
            int quantity = 0;
            for (int i = 0; i < sqls.size(); i++) {
                String sql = sqls.get(i);
                statement.addBatch(sql);
                if (i % UTIL.maxBatch() == 0) {
                    quantity += statement.executeBatch().length;
                    statement.clearBatch();
                }
                if (UTIL.isBatchLog()) {
                    logger.info(">>> {}", sql);
                }
            }
            quantity += statement.executeBatch().length;
            statement.clearBatch();
            if (UTIL.isLogged()) {
                logger.info("删除数据: {}条", quantity);
            }
        }
        return null;
    }
}
